package org.lagou.edu.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @author junbao
 */
@RestController
@RequestMapping("/autoDeliver")
public class AutoDeliverController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/checkState/{userId}")
    public Integer findResumeOpenState(@PathVariable Long userId) {
//        // TODO 普通调用方式
//        // 调用远程服务 -> 简历微服务接口 RestTemplate -> JdbcTemplate
//        Integer forObject = restTemplate.getForObject("http://localhost:8080/resume/openstate/" + userId, Integer.class);
//        return forObject;
//
//        // TODO 从Eureka Server中获取我们关注的那个服务的实例信息以及接口信息
//        // 1、从 Eureka Server中获取lagou-service-resume服务的实例信息（使用客户端对象做这件事）
//        List<ServiceInstance> instances = discoveryClient.getInstances("lagou-service-resume");
//        // 2、如果有多个实例，选择一个使用(负载均衡的过程)
//        ServiceInstance serviceInstance = instances.get(0);
//        // 3、从元数据信息获取host port
//        String host = serviceInstance.getHost();
//        int port = serviceInstance.getPort();
//        String url = "http://" + host + ":" + port + "/resume/openstate/" + userId;
//        System.out.println("===============>>>从EurekaServer集群获取服务实例拼接的url：" + url);
//        // 调用远程服务—> 简历微服务接口  RestTemplate  -> JdbcTempate
//        // httpclient封装好多内容进行远程调用
//        return restTemplate.getForObject(url, Integer.class);

        // TODO 使用Ribbon不需要我们自己获取服务器实例
        String url = "http://lagou-service-resume/resume/port";
        return restTemplate.getForObject(url, Integer.class);

    }

    @HystrixCommand(
            // commandProperties
            commandProperties = {
                    // 每一个属性都是一个HystrixProperties
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
            }
    )
    @GetMapping("/checkPortTimeout")
    public Integer checkPortTimeout() {
        // TODO 使用Ribbon不需要我们自己获取服务器实例
        String url = "http://lagou-service-resume/resume/port";
        return restTemplate.getForObject(url, Integer.class);
    }

    @HystrixCommand(
            // 线程池标识，要保持唯一，不唯一的话就共用了
            threadPoolKey = "findResumeOpenStateTimeoutFallback",
            // 线程池细节属性配置
            threadPoolProperties = {
                    @HystrixProperty(name="coreSize",value = "2"), // 线程数
                    @HystrixProperty(name="maxQueueSize",value="20") // 等待队列长度
            }
            // commandProperties
            ,commandProperties = {
                    // 每一个属性都是一个HystrixProperties
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),


            /**
             * 8秒钟内，请求次数达到2个，并且失败率在50%以上，就跳闸
             * 跳闸后活动窗⼝设置为3s
             */
                    // 统计时间窗口定义
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),
                    // 统计时间窗口内的最小请求数
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
                    // 统计时间窗口内的错误数量百分比阈值
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
                    // 自我修复时的活动窗口长度
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "3000")

    }
            // 服务降级
            ,fallbackMethod = "fallbackMethod"
    )
    @GetMapping("/checkPortTimeoutFallback")
    public Integer checkPortTimeoutFallback() {
        // TODO 使用Ribbon不需要我们自己获取服务器实例
        String url = "http://lagou-service-resume/resume/port";
        return restTemplate.getForObject(url, Integer.class);
    }

    // 定义回退方法，返回预设默认值
    // 注意：该方法形参和返回值与原始方法保持一致
    public Integer fallbackMethod() {
        return -1;
    }
}
